﻿using System;
using System.IO;
using System.Reflection;
using System.Web;

namespace SmartContentModule.Helpers
{
    internal static class IOHelper
    {
        private static string rootPathHash = String.Empty;
        private const string lastModifiedDateStringFormat = "yyyyMMddHHmmss";
        private const string TempFolderName = "SCMTemp";

        /// <summary>
        /// Get full path for url
        /// </summary>
        /// <param name="url">url such as ~/Content/css/general.css</param>
        /// <param name="directory">Directory of file</param>
        /// <returns>Returns full path for file</returns>
        internal static string GetFilePath(string url, string directory)
        {
            try
            {
                if (String.IsNullOrEmpty(url))
                    return String.Empty;

                if (url.StartsWith("/") || url.StartsWith("~"))
                    return ToAbsolutePath(url);
                else
                    return Path.Combine(directory, url.Replace(@"/", @"\"));

                //   return HttpContext.Current.Server.MapPath(url);
            }
            catch (Exception ex)
            {
                ExceptionHelper.HandleError("IOHelper > Parsing " + url + " causes exception.", ex);
                return String.Empty;
            }
        }

        /// <summary>
        /// String representation of last modified time in format yyyyMMddHHmmss
        /// </summary>
        /// <param name="filePath">File path</param>
        /// <returns>Returns last write time</returns>
        internal static string GetLastModificationPostfix(string filePath)
        {
            try
            {
                if (!File.Exists(filePath))
                {
                    ExceptionHelper.HandleWarning("IOHelper > File Not Found ! " + filePath);
                    return String.Empty;
                }

                return File.GetLastWriteTime(filePath).ToString(lastModifiedDateStringFormat);
            }
            catch (Exception ex)
            {
                ExceptionHelper.HandleError("IOHelper > Reading last write time causes error.", ex);
                return DateTime.Today.ToString(lastModifiedDateStringFormat);
            }
        }

        /// <summary>
        /// Gets directory for url
        /// </summary>
        /// <param name="url">url</param>
        /// <returns>Returns directory</returns>
        internal static string GetDirectoryForUrl(string url)
        {
            string filePath = HttpContext.Current.Server.MapPath(url);
            return Path.GetDirectoryName(filePath);
        }

        /// <summary>
        /// Gets new temp file path in VBTemp path
        /// </summary>
        /// <returns>Returns a temp file name</returns>
        internal static string GetTempFilePath()
        {
            string fileName = Path.GetRandomFileName();
            return String.Format(@"{0}\{1}", GetTempFolderPath(), fileName);
        }

        /// <summary>
        /// Gets temp folder in VBTemp path
        /// </summary>
        /// <returns>Returns new sub folder path</returns>
        private static string GetTempFolderPath()
        {
            string directory = Path.GetTempPath();
            string tempPath = String.Format(@"{0}{1}", directory, TempFolderName);
            EnsureTempPath(tempPath);
            tempPath = String.Format(@"{0}\{1}", tempPath, GetBranchTempFolderHash());
            EnsureTempPath(tempPath);
            return tempPath;
        }

        /// <summary>
        /// Application root hash code
        /// </summary>
        /// <returns>Returns application root path hashcode</returns>
        private static string GetBranchTempFolderHash()
        {
            if (String.IsNullOrEmpty(rootPathHash))
                rootPathHash = HttpContext.Current.Server.MapPath("~").GetHashCode().ToString();

            return rootPathHash;
        }

        /// <summary>
        /// Check if file exists
        /// </summary>
        /// <param name="path">Full path for file</param>
        /// <returns>True if file exists, false otherwise</returns>
        internal static bool FileExists(string path)
        {
            return File.Exists(path);
        }

        /// <summary>
        /// Check if folder exists, if not create
        /// </summary>
        /// <param name="path"></param>
        private static void EnsureTempPath(string path)
        {
            if (Directory.Exists(path))
                return;
            try
            {
                Directory.CreateDirectory(path);
            }
            catch (Exception ex)
            {
                ExceptionHelper.HandleError("IOHelper > Error on create temp folder.", ex);
            }
        }

        /// <summary>
        /// Gets file content as string
        /// </summary>
        /// <param name="path">Full path of file</param>
        /// <returns>Returns file content</returns>
        internal static string ReadFile(string path)
        {
            try
            {
                return File.ReadAllText(path);
            }
            catch (Exception ex)
            {
                ExceptionHelper.HandleError("IOHelper > Read file for path '" + path + "' causes error.", ex);
                return String.Empty;
            }
        }

        /// <summary>
        /// Write content to filepath
        /// </summary>
        /// <param name="content">string to write in</param>
        /// <param name="filePath">File path to write to</param>
        internal static void WriteFile(string content, string filePath)
        {
            using (FileStream tempFileStream = File.Create(filePath))
            {
                using (StreamWriter writer = new StreamWriter(tempFileStream))
                {
                    writer.Write(content);
                }
            }
        }

        /// <summary>
        /// Removes a file if exists
        /// </summary>
        /// <param name="filePath">File path to remove</param>
        private static void RemoveFile(string filePath)
        {
            try
            {
                if (FileExists(filePath))
                    File.Delete(filePath);
            }
            catch (Exception)
            {
                ExceptionHelper.HandleWarning("IOHelper > Remove file  failed for path." + filePath);
            }
        }

        /// <summary>
        /// Check if a file is css file
        /// </summary>
        /// <param name="filePath">Full path of file</param>
        /// <returns>True if file is css file, false otherwise</returns>
        internal static bool IsCssFile(string filePath)
        {
            if (!String.IsNullOrEmpty(filePath) && filePath.EndsWith(".css"))
                return true;

            return false;
        }

        /// <summary>
        /// Delete's all files and folders in VBTemp path
        /// </summary>
        internal static void ClearVBTempFolder()
        {
            try
            {
                string tempPath = GetTempFolderPath();
                if (!Directory.Exists(tempPath))
                    return;

                DirectoryInfo directoryInfo = new DirectoryInfo(tempPath);
                foreach (FileInfo file in directoryInfo.GetFiles())
                {
                    file.Delete();
                }
                foreach (DirectoryInfo dir in directoryInfo.GetDirectories())
                {
                    dir.Delete(true);
                }
            }
            catch (Exception ex)
            {
                ExceptionHelper.HandleError("IOHelper > Error on clear temp folder.", ex);
            }
        }

        internal static string ToAbsolutePath(string anyPath)
        {
            try
            {
                if (anyPath.StartsWith("~/") || anyPath.StartsWith("/"))
                {
                    if (HttpContext.Current != null && HttpContext.Current.Server != null)
                    {
                        // Http context available
                        return HttpContext.Current.Server.MapPath(anyPath);
                    }
                    else
                    {
                        //Http context not available
                        anyPath = anyPath.TrimStart('~').TrimStart('/').Replace('/', Path.DirectorySeparatorChar);
                    }
                }

                if (!Path.IsPathRooted(anyPath))
                {
                    string assemblyPath = Assembly.GetExecutingAssembly().CodeBase.Replace("file:///", String.Empty);
                    assemblyPath = Path.GetDirectoryName(assemblyPath);
                    if (Path.GetFileName(assemblyPath).ToLowerInvariant() == "bin")
                    {
                        //Removed bin folder from assembly path to retrieve web site root
                        assemblyPath = Path.GetDirectoryName(assemblyPath);
                        return Path.Combine(assemblyPath, anyPath);
                    }
                    else
                    {
                        //assembly path not a web path
                        return Path.GetFullPath(anyPath);
                    }
                }

                //Default case: Returning Path.GetFullPath
                return Path.GetFullPath(anyPath);
            }
            catch (Exception ex)
            {
                ExceptionHelper.HandleError("IOHelper > failed to get Absolute Path.", ex);
                throw;
            }
        }
    }
}
